package rules;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import managers.ComponentManager;
import managers.FeatureManager;

import components.Component;

import features.Feature;

public class RuleMatcher {
		
	
		public static HashMap<Integer, Component> checkAndUnify(Component pattern, Component input){
			HashMap<Integer, Component> tagMap;
			
			tagMap = unify(pattern, input);
			
			if(tagMap == null)
				if(input.getChildren() != null)
					for(Component subIn : input.getChildren().getChildren()){
						tagMap = checkAndUnify(pattern, subIn);
						if(tagMap != null)
							break;
					}
			
			return tagMap;
		}

		public static HashMap<Integer, Component> unify(Component pattern, Component input){
			boolean match;
			HashMap<Integer, Component> tagMap = new HashMap<Integer, Component>();
			
			if(!pattern.getName().equals(input.getName()))
				return null;
			else {
				HashSet<String> seek = new HashSet<String>();
				HashSet<String> found = new HashSet<String>();
				
				for(Feature feat : pattern.getFeatureList().getFeatureList()){
					if(found.contains(feat.getName()))
						continue;
					seek.add(feat.getName());
					
					for(Feature inFeat : input.getFeatureList().getFeatureList())
						if(feat.getName().equals(inFeat.getName()) && feat.getValue().equals(inFeat.getValue())){
							found.add(feat.getName());

							break;
						}
				}

				seek.removeAll(found);
				if(seek.size() != 0)
					return null;	

				if(input.getChildren() != null)
					for(Component comp : pattern.getChildren().getChildren()){
						match = false;
						
						for(Component inComp : input.getChildren().getChildren()){
							HashMap<Integer, Component> subList = unify(comp, inComp);
							if(subList != null){
								match = true;
								
								for(Map.Entry<Integer, Component> entry : subList.entrySet())
									tagMap.put(entry.getKey(), entry.getValue());
								break;
							}
						}
						if(!match)
							return null;
					}	
				
				int tag;
				if(ComponentManager.getInstance().isLeaf(input.getName()))
					tag = ((RuleInputLeaf)pattern).getTag();
				else
					tag = ((RuleInputPhrase)pattern).getTag();
				
				if(tag != -1)
					tagMap.put(tag, input);
				
				return tagMap;
			}
		}
		
		public static void printComp(Component comp) {
			//System.out.println("***START***\n");
			printComp(comp,0);
			//System.out.println("\n***END***\n");
		}

		public static void printComp(Component comp, int space) {
			for(int i = 0; i < space; i++)
				System.out.print("  ");
			System.out.print(comp.getName());
			boolean first = true;
			for(Feature feat : comp.getFeatureList().getFeatureList())
				if(!FeatureManager.isFeatureDefault(comp.getName(),feat.getName(), feat.getValue())){
					if(first){
						first = false;
						System.out.print(" - ");
					}
						
					System.out.print(feat + " ");
				}
			System.out.println();
			
			if(!ComponentManager.getInstance().isLeaf(comp.getName())){
				for(Component subcomp : comp.getChildren().getChildren())
					printComp(subcomp,space+1);
			}
		}
}


//UNIFICATION VER. 1
	/*	public static boolean unify1(Component pattern, Component input){
			boolean match;
			
			if(!pattern.getName().equals(input.getName()))
				return false;
			else {
				for(Feature feat : pattern.getFeatureList().getFeatureList()){

					match = false;
					for(Feature inFeat : input.getFeatureList().getFeatureList())
						if(feat.getName().equals(inFeat.getName()))
							if(feat.getValue().equals(inFeat.getValue()))
								match = true;
					

					if(!match)
						return false;	
				}

				for(Component comp : pattern.getChildren().getChildren()){
					match = false;
					for(Component inComp : input.getChildren().getChildren())
						if(unify1(comp, inComp))
							match = true;
					if(!match)
						return false;
				}	
				
				return true;
			}
		}*/